#include "threadpool.h"
#include <mysql/mysql.h>

#define __BIG_FILE_SIZE__ (100*1024*1024)  // 大文件边界
int recvn(int sockfd,void *buf,ssize_t length){
    char *p = (char *)buf;
    ssize_t cursize = 0;

    while(cursize < length){
        ssize_t sret = recv(sockfd,p+cursize,length - cursize,0);
        cursize += sret;
    }
    return cursize;
}
int sendn(int sockfd,void *buf,ssize_t length){
    char *p = (char *)buf;
    ssize_t cursize = 0;
    while(cursize < length){
        ssize_t sret = send(sockfd,p+cursize,length-cursize,0);
        cursize += sret;
    }
    return cursize;
}


// 服务端上传
int putsCommand(int sockfd,MYSQL *mysql,char *path,char *filename){

    char full_path[1024] = {0};
    struct stat st;
    memset(&st,0,sizeof(st));

    // 检查文件是否存在
    snprintf(full_path,sizeof(full_path),"%s%s",path,filename);
    // 查数据库表，取出文件的哈希值
    char file_hash[16] = {0};
    int hash_result = 0;

    char query[256];
    snprintf(query,sizeof(query),"select hash from nodes where name = '%s';",filename);

    if(mysql_query(mysql,query)){
        fprintf(stderr,"%s:%s\n","mysql_query",mysql_error(mysql));
        return -1;  // 数据库错误
    }

    MYSQL_RES *res = mysql_store_result(mysql);
    if(res == NULL){
        fprintf(stderr, "mysql_store_result() failed: %s\n", mysql_error(mysql));
        return -1;  // 存储结果失败
    }

    MYSQL_ROW row = mysql_fetch_row(res);
    if(row){
        strncpy(file_hash,row[0],sizeof(file_hash)-1);
        file_hash[sizeof(file_hash)-1] = '\0';
        hash_result = 1;
    }else{
        hash_result = 0; // 文件不存在数据库中
    }

    mysql_free_result(res);


    // 发送文件名和哈希值、文件大小

    snprintf(full_path,sizeof(full_path),"%s/%s",path,file_hash);
    int ret = 0;

    // 发送哈希值
    // 发送哈希值的查询结果
    ret = sendn(sockfd,&hash_result,sizeof(hash_result));
    if(ret==-1){
        printf("send hash_result failed!\n");
        return -1;
    }
    if(hash_result == 1){
        int hash_len = strlen(file_hash);
        ret = sendn(sockfd,&hash_len,sizeof(hash_len));
        printf("ret = %d\n",ret);
        ret = sendn(sockfd,file_hash,hash_len);
        printf("ret = %d\n",ret);
        printf("file_hash = %s\n",file_hash);

    }
    int namelen = strlen(filename);

    // 传输文件名
    ret = sendn(sockfd,&namelen,sizeof(namelen));
    printf("ret = %d\n",ret);
    ret = sendn(sockfd,filename,namelen);
    printf("ret = %d\n",ret);
    printf("filename = %s\n",filename);

    // 传输文件大小
    unsigned long  filesize = st.st_size;
    printf("filesize = %lu\n",filesize);
    sendn(sockfd,&filesize,sizeof(filesize));

    // 打开文件
    int filefd = open(full_path,O_RDONLY);
    if(filefd == -1){
        printf("文件打开失败!\n");
        return -1;
    }

    // 传输文件

        int client_cursize = 0;
        unsigned long sent = client_cursize;
    // 若为大文件
    if(filesize > __BIG_FILE_SIZE__){
        // 接收客户端当前文件大小
        char buf[4096] = {0};
        recvn(sockfd,&client_cursize,sizeof(client_cursize));
        lseek(filefd,client_cursize,SEEK_SET);
        while(sent < filesize){
            unsigned long sendsize = (filesize - sent > sizeof(buf))?sizeof(buf):(filesize-sent);
            ret = read(filefd,buf,sendsize);
            if(ret <= 0) break;
            

            sendn(sockfd,buf,ret);
            sent += ret;

            printf("发送进度：%5.2f%%\r",100.00*sent / filesize);
            fflush(stdout);
        }
    }// end of if
    else{
        //  传输小文件
                
        char buf[1024] = {0};
        while(sent < filesize){
            int sendsize = (filesize - sent > sizeof(buf))?sizeof(buf):(filesize-sent);
            ret = read(filefd,buf,sendsize);
            if(ret <= 0) break;

            int len = ret;
            sendn(sockfd,&len,sizeof(len));
            sendn(sockfd,buf,len);

            sent +=len;
            printf("发送进度：%5.2f%%\r",100.00 * sent / filesize);
            fflush(stdout);
        }
    }


    close(filefd);
    printf("文件发送完毕！总字节数为：%lu\n",sent);

    return 0;
}
